# -*- coding: utf-8 -*-
#   定义类代理
# @Time    ： 2025/11/19  23:29
# @Auther  ： 徐良

from PySide6.QtCore import Qt, QModelIndex, QObject, QEvent, QRect
from PySide6.QtGui import QPainter
from PySide6.QtWidgets import (
    QStyledItemDelegate, QDialog, QVBoxLayout, QTextEdit, QDialogButtonBox,
    QApplication, QWidget, QStyleOptionViewItem, QStyleOptionButton, QStyle
)

from typing import Optional, Union, List, Any, Dict
from domainAndEnum.domainFunction import combox_TypeList, combox_AlignList, combox_WidgetFormList
from mesParts.lineEdit.lineEdits import BodyLineEditInt, BodyLineEditFloat, BodyLineEditStr
from mesParts.comboBox.comboBoxs import ComboxFree

# ------------------------------
# 独立的文本编辑对话框类（可复用）
# ------------------------------
class TextEditDialog(QDialog):
    """字符型字段的自定义编辑对话框"""

    def __init__(self, field_name: str, initial_value: Optional[str], parent: Optional[QWidget] = None):
        super().__init__(parent)
        self._field_name = field_name or "未知字段"
        self._initial_value = initial_value or ""  # 初始值（None 转为空字符串）
        self._init_ui()  # 初始化界面

    def _init_ui(self):
        """初始化对话框界面"""
        # 1. 基础配置
        self.setWindowTitle(f"编辑【{self._field_name}】")
        self.setMinimumSize(500, 350)
        self.setModal(True)  # 模态对话框，阻止其他操作
        self.setStyleSheet("""
            QDialog { background-color: #f8f9fa; }
            QTextEdit { 
                border: 1px solid #dee2e6; 
                border-radius: 4px; 
                padding: 8px; 
                font-size: 14px;
            }
            QDialogButtonBox { margin-top: 10px; }
        """)  # 可选：添加样式美化

        # 2. 文本编辑框（核心控件）
        self.text_edit = QTextEdit()
        self.text_edit.setPlainText(self._initial_value)
        self.text_edit.setLineWrapMode(QTextEdit.WidgetWidth)  # 自动换行
        self.text_edit.setPlaceholderText("请输入内容...")
        self.text_edit.setFocus()  # 打开对话框后自动获取焦点

        # 3. 按钮组
        button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal
        )

        # 4. 布局（带边距，避免控件紧贴边框）
        layout = QVBoxLayout(self)
        layout.setContentsMargins(15, 15, 15, 10)
        layout.setSpacing(10)
        layout.addWidget(self.text_edit)
        layout.addWidget(button_box)

        # 5. 连接信号（绑定按钮事件）
        button_box.accepted.connect(self.accept)  # 确定 → 关闭对话框并返回 Accepted
        button_box.rejected.connect(self.reject)  # 取消 → 关闭对话框并返回 Rejected

    def get_edited_text(self) -> Optional[str]:
        """获取编辑后的文本（空字符串转为 None）"""
        edited_text = self.text_edit.toPlainText().strip()
        return edited_text if edited_text else None


# ------------------------------
# 自定义代理类（简化后，复用 TextEditDialog）
# ------------------------------
class DefineFeldDelegate(QStyledItemDelegate):
    """
    自定义代理：
    1. 字段名为 FID（忽略大小写）的列禁止编辑
    2. 字符型字段（str/None）编辑时弹出自定义对话框
    3. 非字符型字段使用默认编辑器
    """

    def __init__(self, p_dict: Dict[str, Any], parent: Optional[QObject] = None):
        super().__init__(parent)
        if p_dict:
            self.widget_list = p_dict.get('widget', None)
            self.domain_list = p_dict.get('domain', None)

        self._editable_field_types = (str, type(None))  # 字符型字段类型定义


    def paint(self, painter, option, index):
        """绘制单元格内容"""
        column = index.column()
        if self.widget_list:
            widget = self.widget_list[column]
            # 绘制复选框
            if widget.lower() == 'check':
                self._draw_checkbox(painter, option, index)
            else:
                QStyledItemDelegate.paint(self, painter, option, index)


    def flags(self, index: QModelIndex) -> int:
        """重写 flags：控制单元格编辑权限"""
        if not index.isValid():
            return super().flags(index)

        # 获取字段名（处理可能的 None 和非字符串类型）
        model = index.model()
        field_name = model.headerData(index.column(), Qt.Horizontal, Qt.DisplayRole)

        # FID 字段（忽略大小写）禁止编辑
        if isinstance(field_name, str) and field_name.upper() == "FID":
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable  # 仅启用+可选，无编辑权限

        # 其他字段保留默认权限（可编辑）
        return super().flags(index)

    def createEditor(self, parent: QWidget, option: QStyleOptionViewItem,
                     index: QModelIndex) -> Optional[QWidget]:
        """创建编辑器：字符型字段用自定义对话框，其他用默认"""
        if not index.isValid():
            return super().createEditor(parent, option, index)

        # 获取字段信息
        model = index.model()
        field_name = model.headerData(index.column(), Qt.Horizontal, Qt.DisplayRole)
        current_value = index.data(Qt.EditRole)

        # 跳过 FID 字段（双重保险）
        if isinstance(field_name, str) and field_name.upper() == "FID":
            return None

        column = index.column()
        widget = self.widget_list[column]
        if self.domain_list:
            domain = self.domain_list[column]
        else:
            domain = []

        editor = self._get_editor_for_widget(widget, domain, parent, option, index)
        return editor

    def setEditorData(self, editor: QWidget, index: QModelIndex) -> None:
        """设置编辑器初始数据：TextEditDialog 已在构造函数中处理，无需额外操作"""
        if isinstance(editor, TextEditDialog):
            return
        super().setEditorData(editor, index)

    def editorEvent(self, e, model, option, index):
        """处理编辑器事件"""
        column = index.column()
        widget = self.widget_list[column]
        if widget == 'check':
            if e.type() == QEvent.MouseButtonPress:
                model.setData(index, 0 if index.data() else 1)
            return True

        return super().editorEvent(e, model, option, index)


    def setModelData(self, editor: QWidget, model, index: QModelIndex) -> None:
        """将编辑结果写回模型"""
        if isinstance(editor, TextEditDialog):
            # 从对话框获取编辑后的文本
            edited_value = editor.get_edited_text()
            # 写回模型
            model.setData(index, edited_value, Qt.EditRole)
        else:
            super().setModelData(editor, model, index)

    def updateEditorGeometry(self, editor: QWidget, option: QStyleOptionViewItem,
                             index: QModelIndex) -> None:
        """调整编辑器位置：对话框居中显示"""
        if isinstance(editor, TextEditDialog):
            # 对话框居中屏幕
            screen_geometry = QApplication.primaryScreen().availableGeometry()
            dialog_geometry = editor.frameGeometry()
            dialog_geometry.moveCenter(screen_geometry.center())
            editor.move(dialog_geometry.topLeft())
        else:
            super().updateEditorGeometry(editor, option, index)


    def _get_editor_for_widget(self, widget: str, domain: Dict[str, Any],
                               parent: QWidget,
                               option: QStyleOptionViewItem,
                               index: QModelIndex
                               ) -> QWidget:
        """
        根据 widget 类型返回相应的编辑器。

        :param widget_type: 控件类型（如 'LineEditStr', 'LineEditInt' 等）
        :param field_info: 字段信息字典
        :param parent: 父控件
        :param index: 模型索引
        :return: 返回对应的编辑器控件
        """

        if widget == 'check':
            # 复选框无需编辑器，点击即切换
            return None

        if widget == 'BodyLineEditStr':
            return BodyLineEditStr(parent)
        elif widget == 'BodyLineEditInt':
            return BodyLineEditInt(parent)
        elif widget == 'BodyLineEditFloat':
            editor = BodyLineEditFloat(parent)
            return editor
        elif widget == 'TextEditDialog':
            # 创建对话框（传入字段名和初始值）
            model = index.model()
            field_name = model.headerData(index.column(), Qt.Horizontal, Qt.DisplayRole)
            current_value = index.data(Qt.EditRole)

            dialog = TextEditDialog(
                field_name=str(field_name) if field_name else None,
                initial_value=current_value,
                parent=parent
            )
            return dialog

        elif widget == 'ComboxFree':
            editor = ComboxFree(parent)
            editor.addItems(domain)
            return editor

        else:
            print(f"警告：未处理的 widget 类型 '{widget}'，将使用默认编辑器")
            return super().createEditor(parent, option, index)  # 或 return None


    def _draw_checkbox(self, painter, option, index):
        """
        最终版：使用 QStyle 绘制“真实像素”的 checkbox
        不再依赖 pixelMetric，不会被 DPI 缩放导致模糊
        """

        check = QStyleOptionButton()
        check.state = QStyle.State_Enabled

        # 状态
        if index.data() in (1, True):
            check.state |= QStyle.State_On
        else:
            check.state |= QStyle.State_Off

        # 关键：从一个真实 QCheckBox 获取真实 indicator 尺寸
        temp_widget = QWidget()
        actual_size = temp_widget.style().subElementRect(QStyle.SE_CheckBoxIndicator, check, temp_widget)

        w = actual_size.width()
        h = actual_size.height()

        # 居中
        check.rect = QRect(
            option.rect.x() + (option.rect.width() - w) // 2,
            option.rect.y() + (option.rect.height() - h) // 2,
            w, h
        )

        painter.setRenderHint(QPainter.Antialiasing)
        temp_widget.style().drawControl(QStyle.CE_CheckBox, check, painter, temp_widget)
